<script lang="ts">
  import {
    Layout,
    Divider,
    Heading,
    Body,
    Input,
    Icon,
    ColorPicker,
    Button,
    Label,
    File,
    notifications,
    Select,
    Helpers,
  } from "@budibase/bbui"
  import { appStore } from "@/stores/builder"
  import { licensing } from "@/stores/portal/licensing"
  import { API } from "@/api"
  import LockedFeature from "@/pages/builder/_components/LockedFeature.svelte"
  import InfoDisplay from "@/pages/builder/workspace/[application]/design/[workspaceAppId]/[screenId]/[componentId]/_components/Component/InfoDisplay.svelte"

  const DISPLAY_OPTIONS = [
    { label: "Standalone", value: "standalone" },
    { label: "Fullscreen", value: "fullscreen" },
    { label: "Minimal UI", value: "minimal-ui" },
  ]

  let pwaEnabled = $licensing.pwaEnabled
  let uploadingIcons = false

  let pwaConfig = $appStore.pwa || {
    name: "",
    short_name: "",
    description: "",
    icons: [],
    screenshots: [],
    background_color: "#FFFFFF",
    theme_color: "#FFFFFF",
    display: "standalone",
    start_url: "",
    scope: "",
  }

  $: iconCount = pwaConfig.icons?.length || 0
  $: iconStatusText = iconCount ? `${iconCount} icons uploaded` : undefined

  function getCssVariableValue(cssVar: string) {
    try {
      if (cssVar?.startsWith("#")) return cssVar

      const varMatch = cssVar?.match(/var\((.*?)\)/)
      if (!varMatch) return "#FFFFFF"

      const varName = varMatch?.[1]
      const cssValue =
        varName &&
        getComputedStyle(document.documentElement)
          .getPropertyValue(varName)
          .trim()

      return Helpers.rgbToHex(cssValue || "#FFFFFF")
    } catch (error) {
      console.error("Error converting CSS variable:", error)
      return "#FFFFFF"
    }
  }

  async function handlePWAZip(e: CustomEvent) {
    if (!e.detail) {
      notifications.error("No file selected")
      return
    }

    const file: File = e.detail as File

    try {
      uploadingIcons = true
      const data = new FormData()
      data.append("file", file as any)
      const result = await API.uploadPWAZip(data)

      pwaConfig.icons = result.icons
      notifications.success(`Processed ${pwaConfig.icons.length} icons`)
    } catch (error: any) {
      notifications.error("Failed to process zip: " + error.message)
    } finally {
      uploadingIcons = false
    }
  }

  const handleSubmit = async () => {
    try {
      const pwaConfigToSave = {
        ...pwaConfig,
        background_color: getCssVariableValue(pwaConfig.background_color),
        theme_color: getCssVariableValue(pwaConfig.theme_color),
      }

      await API.saveAppMetadata($appStore.appId, { pwa: pwaConfigToSave })
      appStore.update(state => ({ ...state, pwa: pwaConfigToSave }))

      notifications.success("PWA settings saved successfully")
    } catch (error) {
      notifications.error("Error saving PWA settings")
    }
  }

  const handleThemeColorChange = (e: CustomEvent) => {
    pwaConfig.theme_color = e.detail
  }

  const handleBackgroundColorChange = (e: CustomEvent) => {
    pwaConfig.background_color = e.detail
  }
</script>

<LockedFeature
  planType={"Enterprise"}
  enabled={pwaEnabled}
  title={"Progressive web app"}
  description={"Transform your app into an installable, app-like experience with a Progressive Web App (PWA). Developers can configure app details and visuals to create a branded, professional experience for their users."}
  upgradeButtonClick={async () => {
    licensing.goToUpgradePage()
  }}
  showContentWhenDisabled
>
  <Layout gap="S" noPadding>
    {#if pwaEnabled}
      <Layout gap="XS" noPadding>
        <Body size="S">
          Transform your app into an installable, app-like experience with a
          Progressive Web App (PWA). Developers can configure app details and
          visuals to create a branded, professional experience for their users.
        </Body>
      </Layout>
      <InfoDisplay
        icon="info"
        title="PWA Configuration Applies to Entire Workspace"
        body="Within a workspace, you can only make all the apps within that workspace a pwa. If you want a specific
          app to be a pwa, create a new workspace."
      />
      <Divider noMargin />
    {/if}

    <div class="form" class:disabled={!pwaEnabled}>
      <div class="fields">
        <!-- App Details Section -->
        <div class="section">
          <Heading size="S">App details</Heading>
          <Body size="S">
            Define the identity of your app, including its name, description,
            and how it will appear to users when installed.
          </Body>
        </div>

        <div class="field">
          <Label size="L">App name</Label>
          <div>
            <Input
              bind:value={pwaConfig.name}
              placeholder="Full name of your app"
              disabled={!pwaEnabled}
            />
          </div>
        </div>

        <div class="field">
          <Label size="L">Short name</Label>
          <div>
            <Input
              bind:value={pwaConfig.short_name}
              placeholder="Short name for app icon"
              disabled={!pwaEnabled}
            />
          </div>
        </div>

        <div class="field">
          <Label size="L">Description</Label>
          <div>
            <Input
              bind:value={pwaConfig.description}
              placeholder="Describe your app"
              disabled={!pwaEnabled}
            />
          </div>
        </div>
        <Divider noMargin />

        <!-- Appearance Section -->
        <div class="section">
          <Heading size="S">Appearance</Heading>
          <Body size="S">
            Make your app visually appealing with a custom icon and theme. These
            settings control how your app appears on splash screens and device
            interfaces.
          </Body>
        </div>

        <div class="field">
          <div
            style="display: flex; align-items: center; gap: var(--spacing-xs);"
          >
            <Label size="L">App icons</Label>
            <Icon
              size="XS"
              name="info"
              tooltip="Please check our docs for details on a valid ZIP file"
            />
          </div>
          <div>
            <File
              title="Upload zip"
              handleFileTooLarge={() =>
                notifications.error("File too large. 20mb limit")}
              extensions={[".zip"]}
              on:change={handlePWAZip}
              statusText={iconStatusText}
              disabled={!pwaEnabled || uploadingIcons}
            />
          </div>
        </div>

        <div class="field">
          <Label size="L">Background color</Label>
          <div>
            <ColorPicker
              value={pwaConfig.background_color}
              on:change={handleBackgroundColorChange}
            />
          </div>
        </div>

        <div class="field">
          <Label size="L">Theme color</Label>
          <div>
            <ColorPicker
              value={pwaConfig.theme_color}
              on:change={handleThemeColorChange}
            />
          </div>
        </div>
        <Divider noMargin />

        <!-- Manifest Settings Section -->
        <div class="section">
          <Heading size="S">Manifest settings</Heading>
          <Body size="S">
            The manifest settings control how your app behaves once installed.
            These settings define how it appears on the user's device.
            Configuring these fields ensures your app is treated as a
            native-like application.
          </Body>
        </div>

        <div class="field">
          <Label size="L">Display mode</Label>
          <div>
            <Select
              bind:value={pwaConfig.display}
              options={DISPLAY_OPTIONS}
              disabled={!pwaEnabled}
            />
          </div>
        </div>

        <div class="actions">
          <Button cta on:click={handleSubmit} disabled={!pwaEnabled}
            >Save</Button
          >
        </div>
      </div>
    </div>
  </Layout>
</LockedFeature>

<style>
  .form {
    max-width: 100%;
    position: relative;
  }

  .disabled {
    pointer-events: none;
  }

  .fields {
    display: grid;
    grid-gap: var(--spacing-l);
    opacity: var(--form-opacity, 1);
  }

  .disabled .fields {
    --form-opacity: 0.2;
  }

  .field {
    display: grid;
    grid-template-columns: 120px 1fr;
    grid-gap: var(--spacing-l);
    align-items: center;
  }

  .field > div {
    max-width: 300px;
  }

  .section {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-m);
  }

  .actions {
    display: flex;
    margin-top: var(--spacing-xl);
  }
</style>
